package com.wrupple.muba.rest.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestBuilder.Method;
import com.google.gwt.http.client.RequestException;
import com.wrupple.muba.common.domain.UserNamePasswordCredentials;

/**
 * Clase cuya función es hacer request's a elementos que no están dentro de
 * esta aplicación web. Hace una llamada HTTP GET a un URL, incluso si el
 * Request inicialmente falla por SOP del explorador. El proxy intentará:
 * <ol>
 * <li>hace una llamada directa.</li>
 * <li>Si falla, intentará hacer la llamada del lado del servidor.</li>
 * </ol>
 * Y trae una respuesta en texto plano.
 * 
 * <p>
 * Cada Objeto proxy puede ser reutilizado para varios requests.
 * </p>
 * 
 * @author japi
 * 
 */
public class Proxy {
	private final ProxyServiceAsync proxyService = GWT.create(ProxyService.class);

	protected ManejadorRespuestaProxy manejador;
	private Method method = RequestBuilder.GET;
	private UserNamePasswordCredentials credentials;

	/**
	 * Construir un nuevo proxy.
	 * 
	 * @param URL
	 *            Dirección a la que inicialmente se mandará el Request
	 * @param manejador
	 */
	public Proxy(String URL, ManejadorRespuestaProxy manejador) {
		this.manejador = manejador;
		this.manejador.setURL(URL);
	}

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	/**
	 * Hace la petición a la dirección URL de este objeto y manda llamar los
	 * métodos correspondientes en el manejador.
	 */
	public void hacerPeticion() {
		RequestBuilder builder = new RequestBuilder(this.method, this.manejador.getURL());
		if (this.credentials != null) {
			builder.setUser(this.credentials.getUserName());
			builder.setPassword(this.credentials.getPassword());
		}
		try {
			GWT.log("Petición asíncrona a " + this.manejador.getURL(), null);
			builder.setCallback(this.manejador);
			builder.send();
		} catch (RequestException e) {
			GWT.log("Redirigiendo " + this.manejador.getURL() + " a FallbackProxy", e);
			proxyService.proxyServer(this.manejador.getURL(), manejador);
		}
	}

	/**
	 * Regresa el objeto que se ha instanciado en este proxy para manejar las
	 * respuestas.
	 * 
	 * @return
	 */
	public ManejadorRespuestaProxy getManejador() {
		return manejador;
	}

	/**
	 * @param manejador
	 *            EL objeto que será mandado llamar al momento que se reciba
	 *            una respuesta del proxy.
	 */
	public void setManejador(ManejadorRespuestaProxy manejador) {
		this.manejador = manejador;
	}

	/**
	 * @return la URL al que este Proxy manda llamar
	 */
	public String getURL() {
		return this.manejador.getURL();
	}

	/**
	 * @param uRL
	 *            la URL al que este Proxy manda llamar
	 */
	public void setURL(String uRL) {
		this.manejador.setURL(uRL);
	}

	/**
	 * @return the credentials
	 */
	public UserNamePasswordCredentials getCredentials() {
		return credentials;
	}

	/**
	 * @param credentials
	 *            the credentials to set
	 */
	public void setCredentials(UserNamePasswordCredentials credentials) {
		this.credentials = credentials;
	}
}